import _ from "lodash";
import {
  defaultCustomRequestConfig,
  MockConfig,
  MockerStyle,
  MockMode,
  RequestConfig,
} from "./app-request-type.ts";

export default {
  constructMockTemplateAxiosResponse(data: any, config: RequestConfig<any>) {
    return {
      data: data,
      status: 200,
      statusText: "OK",
      headers: { "content-type": "application/json; charset=utf-8" },
      config: _.defaultsDeep(config, defaultCustomRequestConfig),
    };
  },
  isMocked(url: string, mockConfig: Required<MockConfig>): boolean {
    if (mockConfig.mode === MockMode.SERVER) {
      return false;
    }

    if (mockConfig.mode === MockMode.MOCKER) {
      return true;
    }

    const urlConfig = mockConfig.urlConfig;

    const filter = urlConfig.filter((item) => {
      if (typeof item === "string") {
        return item === url;
      }

      return item.url === url;
    });

    const defaultMock =
      typeof mockConfig.defaultMock === "function"
        ? mockConfig.defaultMock(url)
        : mockConfig.defaultMock;

    const includeUrlCustom = filter.length > 0;
    if (!includeUrlCustom) {
      return defaultMock;
    }

    const urlCustom = filter[0];
    if (typeof urlCustom === "string" || urlCustom.mock === undefined) {
      return defaultMock;
    }

    return typeof urlCustom.mock === "function"
      ? urlCustom.mock(url)
      : urlCustom.mock;
  },
  isTemplateMock(url: string, mockConfig: Required<MockConfig>): boolean {
    return (
      this.isMocked(url, mockConfig) &&
      this.mockStyle(url, mockConfig) === MockerStyle.TEMPLATE
    );
  },
  mockStyle(url: string, mockConfig: Required<MockConfig>): MockerStyle {
    const urlConfig = mockConfig.urlConfig;

    const filter = urlConfig.filter((item) => {
      if (typeof item === "string") {
        return item === url;
      }

      return item.url === url;
    });

    const defaultMockerTarget =
      typeof mockConfig.defaultMockerTarget === "function"
        ? mockConfig.defaultMockerTarget()
        : mockConfig.defaultMockerTarget;

    const defaultMockStyle = defaultMockerTarget
      ? MockerStyle.SERVER
      : MockerStyle.TEMPLATE;

    const includeUrlCustom = filter.length > 0;
    if (!includeUrlCustom) {
      return defaultMockStyle;
    }

    const urlCustom = filter[0];
    if (
      typeof urlCustom === "string" ||
      (urlCustom.mockerTarget === undefined &&
        urlCustom.mockerTemplate === undefined)
    ) {
      return defaultMockStyle;
    }

    const urlCustomTarget =
      typeof urlCustom.mockerTarget === "function"
        ? urlCustom.mockerTarget()
        : urlCustom.mockerTarget;

    const urlCustomMockStyle = urlCustomTarget
      ? MockerStyle.SERVER
      : MockerStyle.TEMPLATE;

    return urlCustomMockStyle;
  },
  mockTemplate(url: string, mockConfig: Required<MockConfig>): string | object {
    const urlConfig = mockConfig.urlConfig;

    const filter = urlConfig.filter((item) => {
      if (typeof item === "string") {
        return item === url;
      }

      return item.url === url;
    });

    const defaultMockerTemplate = mockConfig.defaultMockerTemplate;
    const includeUrlCustom = filter.length > 0;
    if (!includeUrlCustom) {
      return typeof defaultMockerTemplate === "function"
        ? defaultMockerTemplate()
        : defaultMockerTemplate;
    }

    const urlCustom = filter[0];
    if (
      typeof urlCustom === "string" ||
      urlCustom.mockerTemplate === undefined
    ) {
      return typeof defaultMockerTemplate === "function"
        ? defaultMockerTemplate()
        : defaultMockerTemplate;
    }

    return typeof urlCustom.mockerTemplate === "function"
      ? urlCustom.mockerTemplate()
      : urlCustom.mockerTemplate;
  },
  mockTarget(url: string, mockConfig: Required<MockConfig>): string {
    if (mockConfig.mode === MockMode.SERVER) {
      return undefined;
    }

    const defaultMockTarget =
      typeof mockConfig.defaultMockerTarget === "function"
        ? mockConfig.defaultMockerTarget()
        : mockConfig.defaultMockerTarget;
    if (mockConfig.mode === MockMode.MOCKER) {
      return defaultMockTarget;
    }

    const urlConfig = mockConfig.urlConfig;
    const filter = urlConfig.filter((item) => {
      if (typeof item === "string") {
        return item === url;
      }

      return item.url === url;
    });

    const includeUrlCustom = filter.length > 0;
    if (!includeUrlCustom) {
      return defaultMockTarget;
    }

    const urlCustom = filter[0];
    if (typeof urlCustom === "string" || urlCustom.mockerTarget === undefined) {
      return defaultMockTarget;
    }

    return typeof urlCustom.mockerTarget === "function"
      ? urlCustom.mockerTarget()
      : urlCustom.mockerTarget;
  },
};
